package com.xframe.xdal.core.handler;

import com.xframe.xdal.core.autofill.AutoProcRuntime;
import com.xframe.xdal.core.constant.DataSourceTypeEnums;
import com.xframe.xdal.core.model.DefModelMapKey;
import com.xframe.xdal.core.model.IModelMapKey;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.serialize.IJSONSer;
import lombok.Data;

import java.util.*;

/**
 * 功能描述: ResultSet结果参数对象
 *
 * @author xufeng
 * @version 1.0
 * @date 2023-03-20
 */
@Data
public class BeanHandlerOptions {


    /**
     * 数据结构
     */
    private ITableInfo tableInfo;

    private IJSONSer jsonSer;
    /**
     * 映射管理器
     */
    private HandlerColumnMapManage handlerColumnMapManage;
    /**
     * 数据源类型
     */
    private DataSourceTypeEnums dataSourceTypeEnums;
    /**
     * 自动填充运行时
     */
    private AutoProcRuntime autoProcRuntime;
    /**
     * 查询的过滤接口
     */
    private IBeanListHandlerCallBack beanListHandlerCallBack;

    /**
     * 集合的类型
     */
    private Class<?> collectionType;

    /**
     * 定义模型的KEY接口
     */
    private IModelMapKey modelMapKey;

    public IModelMapKey getModelMapKey(){
        if(modelMapKey == null){
            modelMapKey = new DefModelMapKey();
        }
        return modelMapKey;
    }



    public void setTableInfo(){
        if(this.handlerColumnMapManage != null) {
            this.handlerColumnMapManage.setMainTableInfo(this.getTableInfo());
        }
    }

    public BeanHandlerOptions(){
        this.tableInfo = null;
        this.handlerColumnMapManage = null;
        this.dataSourceTypeEnums = null;
        this.autoProcRuntime = null;
        this.collectionType = ArrayList.class;;
        this.beanListHandlerCallBack = null;
        this.modelMapKey = null;
    }


    public BeanHandlerOptions(ITableInfo tableInfo,HandlerColumnMapManage handlerColumnMapManage,
                              DataSourceTypeEnums dataSourceTypeEnums,IJSONSer jsonSer,AutoProcRuntime autoProcRuntime){
        this.tableInfo = tableInfo;
        this.handlerColumnMapManage = handlerColumnMapManage;
        this.dataSourceTypeEnums = dataSourceTypeEnums;
        this.autoProcRuntime = autoProcRuntime;
        this.collectionType = ArrayList.class;;
        this.beanListHandlerCallBack = null;
        this.jsonSer = jsonSer;
        this.modelMapKey = null;
        this.setTableInfo();
    }


    public void merge(BeanHandlerOptions options){
        if(options == null){
            return;
        }
        this.beanListHandlerCallBack = options.beanListHandlerCallBack;
        this.collectionType = options.collectionType;
        this.modelMapKey = options.modelMapKey;
    }


    public Class<?> getCollectionType(){
        if(this.collectionType == null){
            this.collectionType = ArrayList.class;
        }
        return this.collectionType;
    }

    public Object getCollectionInstance() throws InstantiationException, IllegalAccessException {
        // 如果类型为空 或者 不是一个集合并且也不是一个map 则设定无效 直接设定为ArrayList.class
        if(this.collectionType == null || (!Collection.class.isAssignableFrom(this.collectionType)
                && !Map.class.isAssignableFrom(this.collectionType))){
            this.collectionType = ArrayList.class;
            return this.collectionType.newInstance();
        }
        if(this.collectionType.isInterface()){
            if(this.collectionType.equals(List.class)){
                this.collectionType = ArrayList.class;
            }
            else if(this.collectionType.equals(Map.class)){
                this.collectionType = HashMap.class;
            }
            else if(this.collectionType.equals(Queue.class)){
                this.collectionType = LinkedList.class;
            }
            else {
                this.collectionType = ArrayList.class;
            }
            return this.collectionType.newInstance();
        }
        try {
            return this.collectionType.newInstance();
        }catch (Exception e){
            this.collectionType = ArrayList.class;
            return this.collectionType.newInstance();
        }
    }


    public <T> T toObject(String json,Class<?> elementBeanType){
        return this.getJsonSer().toObject(json,elementBeanType,this.getTableInfo());
    }
}
